home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-installer.exe / bin / quodlibet / formats / midi.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2014-12-31  |  5KB  |  172 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. import struct
  5. from quodlibet.formats._audio import AudioFile
  6.  
  7. class MidiError(Exception):
  8.     pass
  9.  
  10.  
  11. class MidiFile(AudioFile):
  12.     format = 'MIDI'
  13.     mimes = [
  14.         'audio/midi',
  15.         'audio/x-midi']
  16.     
  17.     def __init__(self, filename):
  18.         h = open(filename, 'rb')
  19.         
  20.         try:
  21.             if h.read(4) != 'MThd':
  22.                 raise MidiError('Not a Midi file')
  23.             h.seek(0, 0)
  24.             
  25.             try:
  26.                 self['~#length'] = read_midi_length(h)
  27.             except Exception:
  28.                 pass
  29.  
  30.         finally:
  31.             h.close()
  32.  
  33.         self.sanitize(filename)
  34.  
  35.     
  36.     def write(self):
  37.         pass
  38.  
  39.     
  40.     def reload(self, *args):
  41.         title = self.get('title')
  42.         super(MidiFile, self).reload(*args)
  43.         if title is not None:
  44.             self.setdefault('title', title)
  45.  
  46.     
  47.     def can_change(self, k = None):
  48.         if k is None:
  49.             return [
  50.                 'title']
  51.         return None == 'title'
  52.  
  53.  
  54. info = MidiFile
  55. types = [
  56.     MidiFile]
  57. extensions = [
  58.     '.mid']
  59. (TEMPO, MIDI) = range(2)
  60.  
  61. def var_int(string):
  62.     val = 0
  63.     i = 0
  64.     while None:
  65.         x = ord(string[i])
  66.         i += 1
  67.         val = (val << 7) + (x & 127)
  68.         if not x & 128:
  69.             return (val, i)
  70.         return None
  71.  
  72.  
  73. def read_track(chunk):
  74.     '''Retuns a list of midi events and tempo change events'''
  75.     tempos = []
  76.     events = []
  77.     deltasum = 0
  78.     status = ''
  79.     while chunk:
  80.         (delta, i) = var_int(chunk)
  81.         deltasum += delta
  82.         chunk = chunk[i:]
  83.         event_type = chunk[0]
  84.         if event_type == '\xff':
  85.             (num, i) = var_int(chunk[2:])
  86.             size = 2 + i + num
  87.             data = chunk[size - num:size]
  88.             if chunk[1] == 'Q':
  89.                 tempo = struct.unpack('>I', '\x00' + data)[0]
  90.                 tempos.append((deltasum, TEMPO, tempo))
  91.             chunk = chunk[size:]
  92.             continue
  93.         if event_type in ('\xf0', '\xf7'):
  94.             chunk = chunk[1 + sum(var_int(chunk[1:])):]
  95.             continue
  96.         event_num = ord(event_type)
  97.         if event_num < 128:
  98.             offset = -1
  99.             event_num = ord(status)
  100.         elif event_num >= 240:
  101.             break
  102.         else:
  103.             offset = 0
  104.             status = event_type
  105.         events.append((deltasum, MIDI, delta))
  106.         if event_num >> 4 in (13, 12):
  107.             chunk = chunk[2 + offset:]
  108.             continue
  109.         chunk = chunk[3 + offset:]
  110.     return (events, tempos)
  111.  
  112.  
  113. def read_midi_length(fileobj):
  114.     '''Returns the duration in seconds. Can raise all kind of errors...'''
  115.     
  116.     def read_chunk(fileobj):
  117.         info = fileobj.read(8)
  118.         chunklen = struct.unpack('>I', info[4:])[0]
  119.         return (info[:4], fileobj.read(chunklen))
  120.  
  121.     (identifier, chunk) = read_chunk(fileobj)
  122.     if identifier != 'MThd':
  123.         raise MidiError('Not a MIDI file')
  124.     format_ = struct.unpack('>H', chunk[:2])[0]
  125.     if format_ > 1:
  126.         raise MidiError('Not supported format %d' % format_)
  127.     ntracks = struct.unpack('>H', chunk[2:4])[0]
  128.     tickdiv = struct.unpack('>H', chunk[4:6])[0]
  129.     if tickdiv >> 15:
  130.         raise MidiError('Not supported timing interval')
  131.     tracks = []
  132.     first_tempos = None
  133.     for tracknum in xrange(ntracks):
  134.         (identifier, chunk) = read_chunk(fileobj)
  135.         if identifier != 'MTrk':
  136.             break
  137.         (events, tempos) = read_track(chunk)
  138.         if not first_tempos:
  139.             pass
  140.         first_tempos = tempos
  141.         if format_ == 1:
  142.             tempos = list(first_tempos)
  143.         events += tempos
  144.         events.sort()
  145.         tracks.append(events)
  146.     
  147.     durations = []
  148.     for events in tracks:
  149.         tempo = 500000
  150.         parts = []
  151.         deltasum = 0
  152.         for dummy, type_, data in events:
  153.             if type_ == TEMPO:
  154.                 parts.append((deltasum, tempo))
  155.                 tempo = data
  156.                 deltasum = 0
  157.                 continue
  158.             deltasum += data
  159.         
  160.         parts.append((deltasum, tempo))
  161.         duration = 0
  162.         for deltasum, tempo in parts:
  163.             quarter = deltasum / float(tickdiv)
  164.             tpq = tempo
  165.             duration += quarter * tpq
  166.         
  167.         duration /= 1000000
  168.         durations.append(duration)
  169.     
  170.     return max(durations)
  171.  
  172.